﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Assert = NUnit.Framework.Assert;

namespace LayeredArchitectureSample.DomainModel.Tests
{
    [TestClass]
    public class TripTests
    {
        [TestMethod]
        public void MakeSureYouCannotMarkAsArrivedATripThatHasAlreadyArrived()
        {
            Location[] locations = CreateFakeLocations();
            WareUnitsCounted[] wares = CreateFakeWares();
            var route = new Route(15, locations);

            var trip = new Trip(new TripEnRoute(1234, wares, route));

            trip.MarkAsArrivedToFinalDestination();

            Assert.Throws<InvalidOperationException>(trip.MarkAsArrivedToFinalDestination);
        }

        [TestMethod]
        public void MakeSureTripDoesNotLoseKnowledgeOfWhatItIsCarryingAndWhere()
        {
            Location[] locations = CreateFakeLocations();
            WareUnitsCounted[] wares = CreateFakeWares();
            Route route = new Route(15, locations);

            var trip = new Trip(new TripEnRoute(1234, wares, route));

            CollectionAssert.AreEquivalent(CreateFakeWares(), trip.Wares);
            Assert.AreEqual(route, trip.Route);

            trip.MarkAsArrivedToFinalDestination();

            CollectionAssert.AreEquivalent(CreateFakeWares(), trip.Wares);
            Assert.AreEqual(route, trip.Route);
        }

        [TestMethod]
        public void MakeSureYouCannotShipATripThatHasSeveralEntriesOfSameWareOnBoard()
        {
            Location[] locations = CreateFakeLocations();
            WareUnitsCounted[] waresWithDuplicates = new[] { new WareUnitsCounted(new Ware(11, "TTX"), 55), new WareUnitsCounted(new Ware(11, "TTX"), 200) };
            var route = new Route(15, locations);

            Assert.Throws<ArgumentException>(() =>
                                                 {
                                                     new Trip(new TripEnRoute(1234, waresWithDuplicates, route));
                                                 });
        }

        private static WareUnitsCounted[] CreateFakeWares()
        {
            return new []{new WareUnitsCounted(new Ware(11, "TTX"), 55)};
        }

        private static Location[] CreateFakeLocations()
        {
            return new[] {new Location(1, "NYC"), new Location(2, "msk"), new Location(3, "SPb")};
        }
    }
}